home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 51 / Amiga Format CD51 (2000-03-10)(Future Publishing)(GB)[!][issue 2000-04].iso / -in_the_mag- / banging_the_metal / qdos / qdos4amiga2 / romsrc / ace / ace_asm
Text File  |  2000-01-03  |  25KB  |  1,098 lines

  1. *
  2. * last modified 02/09/97
  3. *
  4. * AMIGA QDOS SCREEN ACCELERATOR for 32 bit AGA machines
  5. *
  6. * New version supports FLASH in MODE 8 - CPU-intensive!
  7. * Inner loop no longer fits the 68030 cache if flashing.
  8. *
  9. * Version 3.25 by Simon N Goodwin, with thanks to Mark
  10. * J Swift for scanning a listing when I lost the source!
  11. * Listing assumes TABs set to 11 chars
  12. *
  13. qdos    equr    a0    Qdos screen pointer
  14. Plane1    equr    a1    Least significant bitplane
  15. Plane2    equr    a2
  16. Plane3    equr    a3    MODE 8 only
  17. table    equr    a4    Byte translator
  18. *
  19. * Interrupt servers must preserve A5, A6 and A7 (!)
  20. * but all other registers are up for grabs.
  21. *
  22. * Bitplane accumulator registers, added in v3.11
  23. *
  24. RED    equr    d4
  25. BLUE    equr    d5
  26. GREEN    equr    d6
  27. *
  28. * Amiga hardware equates
  29. *
  30. COLOR00 EQU    $DFF180
  31. COLOR01 EQU    $DFF182
  32. COLOR02 EQU    $DFF184
  33. COLOR03 EQU    $DFF186
  34. COLOR04 EQU    $DFF188
  35. COLOR05 EQU    $DFF18A
  36. COLOR06 EQU    $DFF18C
  37. COLOR07 EQU    $DFF18E
  38. *
  39. * QDOS equates
  40. *
  41. BP.INIT equ    $110
  42. CA.GTINT equ    $112
  43. BV.CHRIX equ    $11A
  44. *
  45. * QDOS hardware equates
  46. *
  47. MC_STAT equ    $18063
  48. FLASH_PERIOD equ    16    Fleids per flash change
  49. *
  50. * Default addresses for Qdos and Amiga screen images
  51. *
  52. qlbase    equ    $20000    Base of first QL screen
  53. qlsize    equ    $8000    Size of each QL screen
  54. bp1base equ    $10000    Base of first Amiga bitplane
  55. bp3base equ    $12000    Base of BLUE bitplane in MODE 8
  56. bp2base equ    $14000    Base of second bitplane
  57. *
  58. * Offsets of variables in interrupt linkage
  59. *
  60. link    equ    0    Interrupt link comes first
  61. vector    equ    4    Offset of code address
  62. marker    equ    8    Offset of "ACE3" signature
  63. prefix    equ    12    Number of bytes so far
  64. *
  65. * These variables follow MARKER and are relative to PREFIX
  66. *
  67. limit    equ    0    Count fields down from this
  68. count    equ    1    Current field in sequence
  69. busy    equ    2    Set during interrupt handler
  70. missed    equ    3    (Counted interrupts ignored)
  71. chunks    equ    4    Number of 2K chunks at each pass
  72. soFar    equ    5    Number of 2K chunks already done
  73. smode    equ    6    current screen mode
  74. flash_now  equ    7    Non zero for flash fields
  75. flash_tick equ    8    Counts down between flashes
  76. flash_rate equ    9    Number of fields between flashes
  77. varSize equ    prefix+10 Total bytes of linkage
  78. *
  79. *  ROM header
  80. *
  81. BASE:
  82.     dc.l    $4AFB0001    ROM recognition code
  83.     dc.w    define-BASE    BASIC procs
  84.     dc.w    ROM_START-BASE
  85.     dc.b    0,30,'ACE screen accelerator v3.26 ',$A
  86. *
  87. *  start of ROM code
  88. *
  89. ROM_START:
  90.     movem.l d0-d3/a0-a3,-(a7)
  91.  
  92.     lea    BASE(pc),a0
  93.     cmp.l    #$1000000,a0    FAST RAM?
  94.     bmi    ROM_EXIT     No, user decides
  95.  
  96.     moveq    #0,d0
  97.     trap    #1
  98.  
  99.     move.b    161(a0),d0    Check CPU version
  100.     cmp.b    #$30,d0        < 030, user decides
  101.     bcs.s    ROM_EXIT
  102.  
  103.     bsr    mblit_on
  104.  
  105. ROM_EXIT:
  106.     movem.l (a7)+,d0-d3/a0-a3
  107.     rts
  108. *
  109. * This is the routine that redraws the whole screen
  110. * On entry A3 -> Linkage-8; A6 -> Qdos variables
  111. *
  112. AceVars    equ    prefix+8     A3 offset to LIMIT
  113. *
  114. redraw:
  115.     btst    #7,$1813E
  116.     beq    mblit_off
  117.  
  118.     tst.b    busy+AceVars(a3)    Prevent re-entrancy
  119.     beq.s    update
  120. *
  121. * Code to work out the number of interrupts MISSED (while ACE is
  122. * busy) commented out for version 3.16 as Qdos can't cope with
  123. * missed interrupts anyway, and I needed the variable to set the
  124. * proportion of the screen to be updated (1..16, as SCR_PRIORITY)
  125. *
  126. * ignore addq.b    #1,missed+AceVars(a3)
  127. skip:
  128.     rts
  129. *
  130. update:
  131.     move.b    flash_rate+AceVars(a3),d1
  132.     beq.s    limit_ok         Not ever flashing!
  133.  
  134.     subq.b    #1,flash_tick+AceVars(a3)
  135.     bne.s    limit_ok         No change
  136.  
  137.     move.b    d1,flash_tick+AceVars(a3)
  138.     not.b    flash_now+AceVars(a3)    Toggle flash flag
  139.  
  140. *    move.b    missed+AceVars(a3),d1
  141. *    beq.s    limit_ok         No interrupts missed
  142. *
  143. *    addq.b    #1,d1            Count one that worked
  144. *    clr.b    missed+AceVars(a3)    Keep checking
  145. *    cmp.b    limit+AceVars(a3),d1    Can the CPU keep up?
  146. *    bls.s    limit_ok         There is enough time
  147. *
  148. *    move.b    d1,limit+AceVars(a3)    Increase limit
  149. *
  150. limit_ok:
  151.     subq.b    #1,count+AceVars(a3)
  152.     bne.s    skip            The time is NOT nigh
  153. *
  154.     st    busy+AceVars(a3)        Flag critical region
  155.     move.b    limit+AceVars(a3),count+AceVars(a3)
  156.     lea.l    bp1base,Plane1
  157.     lea.l    bp2base,Plane2
  158.     lea.l    qlbase+qlsize,qdos    Point at screen 2
  159.     move.b    MC_STAT,d2        Check if it's in use
  160.     bmi.s    chkmod
  161. *
  162.     lea.l    -qlsize(qdos),qdos    Wind back to screen 1
  163. *
  164. * Check if mode has changed
  165. *
  166. chkmod:
  167.     cmp.b    smode+AceVars(a3),d2
  168.     beq.s    chksho
  169. *
  170.     bsr    ace_cop
  171.     move.b    d2,smode+AceVars(a3)
  172. *
  173. chksho:
  174.     btst    #1,d2        check blanking bit
  175.     bne    done        and exit if set
  176. *
  177. * Work out which chunk needs to be updated next, and adjust pointers
  178. *
  179. based:
  180.     move.w    #2048/8,d3    Iterations per 2K chunk
  181.     moveq    #0,d4
  182.     move.b    chunks+AceVars(a3),d4
  183.     moveq    #0,d5
  184.     move.b    soFar+AceVars(a3),d5
  185. *
  186. * Advance input and output pointers past data previously processed
  187. *
  188.     move.l    d5,d6
  189.     lsl.l    #8,d6
  190.     add.l    d6,d6        * 512 for output offsets
  191.     add.l    d6,Plane1
  192.     add.l    d6,qdos
  193.     add.l    d6,Plane2
  194.     add.l    d6,qdos        Qdos gets scanned fastest
  195.     add.l    d6,qdos
  196.     add.l    d6,qdos        We'll need D6 again later
  197. *
  198. * Work out where we're going to end up
  199. *
  200.     add.b    d4,d5
  201.     cmp.b    #16,d5        Up to end of screen?
  202.     bcs.s    nextChunk
  203. *
  204.     sub.b    #16,d5        Compute potential overrun
  205.     sub.b    d5,d4        Do that much less, then
  206.     clr.b    d5        Restart at the beginning
  207. *
  208. nextChunk:
  209.     move.b    d5,soFar+AceVars(a3)
  210.     mulu.w    d4,d3        D3 is loop count, D3.H=0
  211.     subq.w    #1,d3        Adjust for DBRA
  212.  
  213. *    move.w    #6,$DFF180    Show beam position
  214. *
  215. * If we're running on a CPU with a data cache, we should disable cache
  216. * allocation while redrawing the screen to avoid swamping it with data
  217. * that we do not intend to re-use, and wiping out MODE 8 table data.
  218. *
  219.     move.b    161(a6),d0    Check CPU version
  220.     cmp.b    #$30,d0
  221.     bcs.s    decached     No data cache before 68030
  222. *
  223. * If we're in MODE 8 we need to prime the data cache with our byteTable
  224. *
  225.     btst    #3,d2         MODE 8 ?
  226.     beq.s    noPrime
  227. *
  228.     lea.l    byteTable(pc),table
  229.     moveq    #256/4-1,d1
  230. primer:
  231.     tst.l    (table)+     Get it all into the cache
  232.     dbra    d1,primer
  233. *
  234. noPrime:
  235.     dc.w    $4E7A,$1002    MOVEC CACR,D1
  236.     cmp.b    #$30,d0        Is this a 68030?
  237.     bne.s    after030
  238. *
  239. * 68030 data cache disabling code
  240. *
  241.     btst    #8,d1
  242.     beq    mblit_off    disable if instr cache off
  243.  
  244.     move.l    d1,d7        Save old setting
  245. *     beq.s     decached
  246. *
  247.     bset    #9,d1        Disable data allocation
  248.     dc.w    $4E7B,$1002    MOVEC D1,CACR
  249.     bra.s    decached
  250. *
  251. * 68040/060 data cache disabling code; leaves prior DTT0 in D7
  252. *
  253. after030:
  254.     btst    #15,d1
  255.     beq    mblit_off    disable if instr cache off
  256.  
  257.     dc.w    $4E7A,$7006    MOVEC DTT0,D7
  258.     move.l    #$C060,d1    Don't cache 0..16 Mb
  259.     dc.w    $4E7B,$1006    MOVEC D1,DTT0
  260. *
  261. * Check the mode to determine the format of the Qdos screen
  262. *
  263. decached:
  264.     btst    #3,d2        Mode 8 ?
  265.     bne.s    mode8
  266. *
  267. * Algorithmic version, reads 8 bytes and unscrambles them to 2 bitplanes
  268. * Input read to D0 and D5 goes to D2 and D3; D4 scratch, D6 counts loops
  269. *
  270. mode4:
  271.     move.w    d3,d1
  272.     add.l    d6,Plane1    MODE 4 outputs 2 for 1
  273.     add.l    d6,Plane2
  274. *
  275. next8:
  276.     movem.l    (qdos)+,d0/d5    Scrambled long words: ABCD EFGH
  277.     move.l    d0,d2        Set A in high byte of result
  278.     lsl.l    #8,d0        Align BC in the high word
  279.     move.l    d2,d4        Save low byte in D for later
  280.     swap    d0        Low word is now BC
  281.     swap    d2        CDAB
  282.     move.l    d0,d3        Set up B, but in low word
  283.     move.b    d4,d3        Set up D, again low for now
  284.     move.b    d0,d2        AC set in low word
  285. *
  286. * So far we have set AC and BD in the low word of our output registers
  287. * Next step is to work out the other word, and get both words in order
  288. *
  289.     move.l    d5,d4        Save H for later
  290.     swap    d5        GHEF
  291.     swap    d2        AC??
  292.     move.w    d5,d2        Set E in place
  293.     move.l    d4,d5        EFGH
  294.     lsr.l    #8,d5        0EFG
  295.     move.b    d5,d2        Set G in place
  296.     move.l    d2,(Plane2)+    Store ACEG green bits
  297.     swap    d3        BD??
  298.     move.w    d5,d3        BDF?
  299.     move.b    d4,d3        BDFH
  300.     move.l    d3,(Plane1)+    Write out red bits
  301.     dbra    d1,next8
  302. *
  303.     bra    CacheIn
  304. *
  305. * MODE 8 support - added in version 3.11
  306. *
  307. mode8:
  308.     lea.l    byteTable(pc),table    Point to start of table
  309.     tst.b    flash_now+AceVars(a3)
  310.     bne    do_flash
  311. *
  312. mode8_nf:
  313.     moveq    #0,d0        Ensure byte values are unsigned longs
  314.     move.l    a3,-(a7)
  315.     lea.l    bp3base,Plane3    Extra plane pointer for eight colours
  316.     add.l    d6,Plane3
  317. *
  318. next2:
  319.     move.l    (qdos)+,d1
  320. *
  321. * Convert two Qdos screen bytes into three packed nybbles for the bitplanes
  322. *
  323.     rol.l    #8,d1        Move MSB (green byte) to LSB
  324.     move.b    d1,d0        Make it an unsigned long value
  325.     moveq    #15,d2        Mask for low nybble
  326.     and.b    0(table,d0.l),d2    Get four packed green bits
  327.     lsl.l    #4,GREEN     Make room
  328.     or.b    d2,GREEN
  329.     rol.l    #8,d1        Get blue and red byte to LSB
  330.     move.b    d1,d0
  331.     moveq    #15,d2        Mask for packed red bits
  332.     move.b    0(table,d0.l),d0
  333.     lsl.l    #4,RED        Make room
  334.     and.b    d0,d2        Extract red bits
  335.     lsl.l    #4,BLUE    Make room
  336.     lsr.b    #4,d0        Move blue pack to low nybble
  337.     or.b    d2,RED
  338.     or.b    d0,BLUE
  339. *
  340. * Now do the next two Qdos bytes, from the other half of D1
  341. *
  342.     rol.l    #8,d1        Move MSB (green byte) to LSB
  343.     move.b    d1,d0        Make it an unsigned long value
  344.     moveq    #15,d2        Mask for low nybble
  345.     and.b    0(table,d0.l),d2    Get four packed green bits
  346.     lsl.l    #4,GREEN     Make room
  347.     or.b    d2,GREEN
  348.     rol.l    #8,d1        Get blue and red byte to LSB
  349.     move.b    d1,d0
  350.     moveq    #15,d2        Mask for packed red bits
  351.     move.b    0(table,d0.l),d0
  352.     lsl.l    #4,RED        Make room
  353.     and.b    d0,d2        Extract red bits
  354.     lsl.l    #4,BLUE        Make room
  355.     lsr.b    #4,d0        Move blue pack to low nybble
  356.     or.b    d2,RED
  357.     or.b    d0,BLUE
  358. *
  359. * Pick up another Qdos long word and repeat to get a whole word for each bitplane
  360. *
  361.     move.l    (qdos)+,d1
  362. *
  363. * Optimisation to speed up black areas of the screen. Overhead is just this test
  364. *
  365.     beq.s    blackOut     Skip prevarication
  366. *
  367.     rol.l    #8,d1        Move MSB (green byte) to LSB
  368.     move.b    d1,d0        Make it an unsigned long value
  369.     moveq    #15,d2        Mask for low nybble
  370.     and.b    0(table,d0.l),d2    Get four packed green bits
  371.     lsl.l    #4,GREEN     Make room
  372.     or.b    d2,GREEN
  373.     rol.l    #8,d1        Get blue and red byte to LSB
  374.     move.b    d1,d0
  375.     moveq    #15,d2        Mask for packed red bits
  376.     move.b    0(table,d0.l),d0
  377.     lsl.l    #4,RED        Make room
  378.     and.b    d0,d2        Extract red bits
  379.     lsl.l    #4,BLUE        Make room
  380.     lsr.b    #4,d0        Move blue pack to low nybble
  381.     or.b    d2,RED
  382.     or.b    d0,BLUE
  383. *
  384. * Time to sort out the remaining Qdos word
  385. *
  386.     rol.l    #8,d1        Move MSB (green byte) to LSB
  387.     move.b    d1,d0        Make it an unsigned long value
  388.     moveq    #15,d2        Mask for low nybble
  389.     and.b    0(table,d0.l),d2    Get four packed green bits
  390.     lsl.l    #4,GREEN     Make room
  391.     or.b    d2,GREEN
  392. *
  393. * If D3 is even we've got long words to write out
  394. *
  395.     btst    #0,d3
  396.     bne.s    noWrite
  397. *
  398. * These three nybbles complete long bitplane values which must be stored
  399. *
  400.     move.l    GREEN,(Plane3)+
  401.     rol.l    #8,d1        Get blue and red byte to LSB
  402.     move.b    d1,d0
  403.     moveq    #15,d2        Mask for packed red bits
  404.     move.b    0(table,d0.l),d0
  405.     lsl.l    #4,RED        Make room
  406.     and.b    d0,d2        Extract red bits
  407.     or.b    d2,RED
  408.     move.l    RED,(Plane2)+
  409.     lsl.l    #4,BLUE        Make room
  410.     lsr.b    #4,d0        Move blue pack to low nybble
  411.     or.b    d0,BLUE
  412.     move.l    BLUE,(Plane1)+
  413.     bra.s    CarryOn
  414. *
  415. * A quick hack to save time if even input long words are zero (8 black pixels)
  416. *
  417. blackOut:
  418.     lsl.l    #8,GREEN
  419.     lsl.l    #8,RED
  420.     lsl.l    #8,BLUE
  421. *
  422. * If D3 is even we've got long words to write out
  423. *
  424.     btst    #0,d3
  425.     bne.s    CarryOn    Go round again for the next word
  426. *
  427.     move.l    BLUE,(Plane1)+
  428.     move.l    RED,(Plane2)+
  429.     move.l    GREEN,(Plane3)+
  430.     bra.s    CarryOn
  431. *
  432. * Continue to accumulate in registers as we have not yet got long values
  433. *
  434. noWrite:
  435.     rol.l    #8,d1        Get blue and red byte to LSB
  436.     move.b    d1,d0
  437.     moveq    #15,d2        Mask for packed red bits
  438.     move.b    0(table,d0.l),d0
  439.     lsl.l    #4,RED        Make room
  440.     and.b    d0,d2        Extract red bits
  441.     lsl.l    #4,BLUE        Make room
  442.     lsr.b    #4,d0        Move blue pack to low nybble
  443.     or.b    d2,RED
  444.     or.b    d0,BLUE
  445. CarryOn:
  446.     dbra    d3,next2
  447.     move.l    (a7)+,a3     Restore -> AceVars
  448. *
  449. CacheIn:
  450.     move.b    161(a6),d1    Check for data cache
  451.     cmp.b    #$30,d1    68030?
  452.     bcs.s    done
  453. *
  454.     beq.s    enable030
  455. *
  456. * Revert to prior setting of DTT0 on 68040 or 68060
  457. *
  458.     dc.w    $4E7B,$7006    MOVEC D7,DTT0
  459.     bra.s    done
  460. *
  461. * Revert to prior setting of CACR on 68030
  462. *
  463. enable030:
  464.     dc.w    $4E7B,$7002    MOVEC D7,CACR
  465.  
  466. done:
  467.     clr.b    busy+AceVars(a3)
  468.  
  469. *    move.w    #0,$DFF180    Show beam position
  470.  
  471.     rts
  472. *
  473. * New routine for v3.22 to render a (potentially) flashing field
  474. *
  475. do_flash:
  476.     moveq    #0,d0        Ensure byte values are unsigned longs
  477.     move.l    a3,-(a7)
  478.     lea.l    bp3base,Plane3    Extra plane pointer for eight colours
  479.     move.l    d7,-(a7)     More scratch space needed
  480.     add.l    d6,Plane3
  481. *
  482. Fnext2:
  483.     move.l    (qdos)+,d1
  484. *
  485. * Check for flash bits and process them if necessary
  486. *
  487. * Optimisation for no change in this long word
  488.  
  489.     move.l    #$55005500,d2    Mask for just the flash bits
  490.     and.l    d1,d2
  491.     beq.s    No_bits1     Skip if no flash bits set
  492.  
  493.     moveq    #30,d0        First flast bit # to test
  494.     move.l    #$7F3FFFFF,d2    Mask excludes first pixel colour
  495.  
  496. Flash1:
  497.     btst    d0,d1        New flash bit set?
  498.     bne.s    Toggle1
  499.     tst.l    d3        Same as what?
  500.     bpl.s    Pixel1
  501.  
  502. Tweak1:
  503.     ror.l    #2,d7        Push colour mask along
  504.     and.l    d2,d1        Obscure old colour of pixel
  505.     or.l    d7,d1        Replace with flash colour
  506.  
  507. Pixel1:
  508.     ror.l    #2,d2        Next pixel mask (?)
  509.     bpl.s    Done1        Back to the start!
  510.     subq.b    #2,d0        Next flash bit
  511.  
  512.     cmp.b    #22,d0
  513.     bne.s    Flash1
  514.     ror.l    #8,d2        Move mask over odd RB byte
  515.     ror.l    #8,d7        Just in case flashing now
  516.     subq.b    #8,d0
  517.     bra.s    Flash1
  518.  
  519. Toggle1:
  520.     bchg    #31,d3        Toggle flag in MS bit
  521.     bne.s    Tweak1        Once more with feeling
  522.     move.l    d2,d7
  523.     not.l    d7        Mask for pixel colour
  524.     and.l    d1,d7
  525.     bra.s    Pixel1
  526.  
  527. No_bits1:
  528.     tst.l    d3        MS bit set if flashing NOW
  529.     bpl.s    Flashed1
  530. *
  531. * A whole line of eight flashing pixels - do these the quick way!
  532. *
  533.     lsl.l    #8,RED
  534.     btst    #25,d7        Red bit set in background?
  535.     sne    RED        If so, set eight red bits
  536.     lsl.l    #8,GREEN
  537.     btst    #1,d7        Green bit
  538.     sne    GREEN
  539.     lsl.l    #8,BLUE        Make room for 8 blue bits
  540.     btst    #24,d7
  541.     sne    BLUE
  542.     bra.s    Byten1        Skip to next fetch
  543.  
  544. Done1    ror.l    #8,d7        Colour back to top bits
  545. *
  546. * Convert two Qdos screen bytes into three packed nybbles for the bitplanes
  547. *
  548. Flashed1:
  549.     rol.l    #8,d1        Move MSB (green byte) to LSB
  550.     move.b    d1,d0        Make it an unsigned long value
  551.     moveq    #15,d2        Mask for low nybble
  552.     and.b    0(table,d0.l),d2    Get four packed green bits
  553.     lsl.l    #4,GREEN     Make room
  554.     or.b    d2,GREEN
  555.     rol.l    #8,d1        Get blue and red byte to LSB
  556.     move.b    d1,d0
  557.     moveq    #15,d2        Mask for packed red bits
  558.     move.b    0(table,d0.l),d0
  559.     lsl.l    #4,RED        Make room
  560.     and.b    d0,d2        Extract red bits
  561.     lsl.l    #4,BLUE        Make room
  562.     lsr.b    #4,d0        Move blue pack to low nybble
  563.     or.b    d2,RED
  564.     or.b    d0,BLUE
  565. *
  566. * Now do the next two Qdos bytes, from the other half of D1
  567. *
  568.     rol.l    #8,d1        Move MSB (green byte) to LSB
  569.     move.b    d1,d0        Make it an unsigned long value
  570.     moveq    #15,d2        Mask for low nybble
  571.     and.b    0(table,d0.l),d2    Get four packed green bits
  572.     lsl.l    #4,GREEN     Make room
  573.     or.b    d2,GREEN
  574.     rol.l    #8,d1        Get blue and red byte to LSB
  575.     move.b    d1,d0
  576.     moveq    #15,d2        Mask for packed red bits
  577.     move.b    0(table,d0.l),d0
  578.     lsl.l    #4,RED        Make room
  579.     and.b    d0,d2        Extract red bits
  580.     lsl.l    #4,BLUE        Make room
  581.     lsr.b    #4,d0        Move blue pack to low nybble
  582.     or.b    d2,RED
  583.     or.b    d0,BLUE
  584. *
  585. * Pick up another long word and repeat to get a whole word for each bitplane
  586. *
  587. Byten1:
  588.     move.l    (qdos)+,d1
  589. *
  590. * Check for flash bits and process them if necessary (v3.22 extension)
  591. *
  592.     move.l    #$55005500,d2    Mask for just the flash bits
  593.     and.l    d1,d2
  594.     beq.s    No_bits2     Skip if no flash bits set
  595.  
  596.     moveq    #30,d0        First flast bit # to test
  597.     move.l    #$7F3FFFFF,d2    Mask excludes first pixel colour
  598.  
  599. Flash2:
  600.     btst    d0,d1        New flash bit set?
  601.     bne.s    Toggle2
  602.     tst.l    d3        Same as what?
  603.     bpl.s    Pixel2
  604.  
  605. Tweak2:
  606.     ror.l    #2,d7        Push colour mask along
  607.     and.l    d2,d1        Obscure old colour of pixel
  608.     or.l    d7,d1        Replace with flash colour
  609.  
  610. Pixel2:
  611.     ror.l    #2,d2        Next pixel mask (?)
  612.     bpl.s    Done2        Back to the start!
  613.     subq.b    #2,d0        Next flash bit
  614.     cmp.b    #22,d0
  615.     bne.s    Flash2
  616.  
  617.     ror.l    #8,d2        Move mask over odd RB byte
  618.     ror.l    #8,d7        Just in case flashing now
  619.     subq.b    #8,d0
  620.     bra.s    Flash2
  621.  
  622. Toggle2:
  623.     bchg    #31,d3        Toggle flag in MS bit
  624.     bne.s    Tweak2        Last flash in this set
  625.     move.l    d2,d7
  626.     not.l    d7        Mask for pixel colour
  627.     and.l    d1,d7
  628.     bra.s    Pixel2
  629.  
  630. No_bits2:
  631.     tst.l    d3        MS bit set if flashing NOW
  632.     bpl.s    Flashed2
  633. *
  634. * A whole line of eight flashing pixels - do these the quick way!
  635. *
  636.     lsl.l    #8,RED
  637.     btst    #25,d7        Red bit set in background?
  638.     sne    RED        If so, set eight red bits
  639.     lsl.l    #8,GREEN
  640.     btst    #1,d7        Green bit before rotation
  641.     sne    GREEN
  642.     lsl.l    #8,BLUE        Make room for 8 blue bits
  643.     btst    #24,d7
  644.     sne    BLUE
  645.     bra.s    Byten2
  646.  
  647. Done2:
  648.     ror.l    #8,d7        Colour back to top bits
  649. *
  650. * Convert two Qdos screen bytes into three packed nybbles for the bitplanes
  651. *
  652. Flashed2 tst.l    d1
  653. *
  654. * Optimisation to speed up black areas of the screen
  655. *
  656.     beq.s    FblackOut    Skip prevarication
  657.  
  658.     rol.l    #8,d1        Move MSB (green byte) to LSB
  659.     move.b    d1,d0        Make it an unsigned long value
  660.     moveq    #15,d2        Mask for low nybble
  661.     and.b    0(table,d0.l),d2    Get four packed green bits
  662.     lsl.l    #4,GREEN     Make room
  663.     or.b    d2,GREEN
  664.     rol.l    #8,d1        Get blue and red byte to LSB
  665.     move.b    d1,d0
  666.     moveq    #15,d2        Mask for packed red bits
  667.     move.b    0(table,d0.l),d0
  668.     lsl.l    #4,RED        Make room
  669.     and.b    d0,d2        Extract red bits
  670.     lsl.l    #4,BLUE    Make room
  671.     lsr.b    #4,d0        Move blue pack to low nybble
  672.     or.b    d2,RED
  673.     or.b    d0,BLUE
  674. *
  675. * Time to sort out the remaining Qdos word
  676. *
  677.     rol.l    #8,d1        Move MSB (green byte) to LSB
  678.     move.b    d1,d0        Make it an unsigned long value
  679.     moveq    #15,d2        Mask for low nybble
  680.     and.b    0(table,d0.l),d2    Get four packed green bits
  681.     lsl.l    #4,GREEN     Make room
  682.     or.b    d2,GREEN
  683. *
  684. * If D3 is even we've got long words to write out
  685. *
  686.     btst    #0,d3
  687.     bne.s    FnoWrite
  688. *
  689. * These three nybbles complete long bitplane values which must be stored
  690. *
  691.     move.l    GREEN,(Plane3)+
  692.     rol.l    #8,d1        Get blue and red byte to LSB
  693.     move.b    d1,d0
  694.     moveq    #15,d2        Mask for packed red bits
  695.     move.b    0(table,d0.l),d0
  696.     lsl.l    #4,RED        Make room
  697.     and.b    d0,d2        Extract red bits
  698.     or.b    d2,RED
  699.     move.l    RED,(Plane2)+
  700.     lsl.l    #4,BLUE        Make room
  701.     lsr.b    #4,d0        Move blue pack to low nybble
  702.     or.b    d0,BLUE
  703. *
  704. * Before posting the last write, see if the flash flag needs toggling
  705. *
  706. Fcheck:
  707.     moveq    #31,d0        Mask for 256 pixel wide plane
  708.     move.l    Plane3,d1
  709.     and.l    d1,d0        Test low bits for next write
  710.     bne.s    in_line
  711.     ext.l    d3        Reset flash flag, new line
  712.  
  713. in_line:
  714.     move.l     BLUE,(Plane1)+
  715.     bra.s    FCarryOn
  716. *
  717. * Quick tweak saves time if even input long words are zero (8 black pixels)
  718. *
  719. FblackOut:
  720.     lsl.l    #8,GREEN
  721.     lsl.l    #8,RED
  722.     lsl.l    #8,BLUE
  723.  
  724. Byten2:
  725.     btst    #0,d3        Have we got a whole long word yet?
  726.     bne.s    FCarryOn     Go round again for the next word
  727. *
  728.     move.l    RED,(Plane2)+
  729.     move.l    GREEN,(Plane3)+
  730.     bra.s    Fcheck
  731. *
  732. * Continue to accumulate in registers as we have not yet got long values
  733. *
  734. FnoWrite:
  735.     rol.l    #8,d1        Get blue and red byte to LSB
  736.     move.b    d1,d0
  737.     moveq    #15,d2        Mask for packed red bits
  738.     move.b    0(table,d0.l),d0
  739.     lsl.l    #4,RED        Make room
  740.     and.b    d0,d2        Extract red bits
  741.     lsl.l    #4,BLUE        Make room
  742.     lsr.b    #4,d0        Move blue pack to low nybble
  743.     or.b    d2,RED
  744.     or.b    d0,BLUE
  745.  
  746. FCarryOn:
  747.     dbra    d3,Fnext2
  748.     move.l    (a7)+,d7
  749.     move.l    (a7)+,a3
  750.     bra.w    CacheIn
  751. *
  752. * Subroutine to change copper list to suit ACE
  753. *
  754. ace_cop:
  755.     bset    #7,$1813E    disable screen blitter
  756.     move.w    #$0000,COLOR00
  757.     move.b    MC_STAT,d2
  758.     btst    #3,d2
  759.     bne.s    ace_cop8
  760. *
  761. ace_cop4:
  762.     move.w    #76,99974    DDFSTART
  763.     move.w    #204,99978    DDFSTOP
  764.     move.w    #-4,99982    Modulo
  765.     move.w    #-4,99986    Modulo
  766.     move.w    #$A200,100002
  767.     btst    #1,d2
  768.     bne    blnkit
  769.     move.w    #$0F00,COLOR01
  770.     move.w    #$00F0,COLOR02
  771.     move.w    #$0FFF,COLOR03
  772.     rts
  773. *
  774. ace_cop8:
  775.     move.w    #72,99974    DDFSTART
  776.     move.w    #200,99978    DDFSTOP
  777.     move.w    #-2,99982    Modulo
  778.     move.w    #-2,99986    Modulo
  779.     move.w    #$3200,100002
  780.     btst    #1,d2
  781.     bne.s    blnkit
  782.     move.w    #$000F,COLOR01
  783.     move.w    #$0F00,COLOR02
  784.     move.w    #$0F0F,COLOR03
  785.     move.w    #$00F0,COLOR04
  786.     move.w    #$00FF,COLOR05
  787.     move.w    #$0FF0,COLOR06
  788.     move.w    #$0FFF,COLOR07
  789.     rts
  790. *
  791. blnkit:
  792.     move.w    #$0000,COLOR01
  793.     move.w    #$0000,COLOR02
  794.     move.w    #$0000,COLOR03
  795.     rts
  796. *
  797. * sub to change copper list to suit blitter
  798. *
  799. blt_cop:
  800.     bclr    #7,$1813E    enable screen blitter
  801.     move.w    #76,99974    DDFSTART
  802.     move.w    #204,99978    DDFSTOP
  803.     move.w    #-4,99982    Modulo
  804.     move.w    #-4,99986    Modulo
  805.     move.w    #$A200,100002
  806.     move.w    #$0000,COLOR00
  807.     move.w    #$0FFF,COLOR03
  808. *
  809.     move.b    MC_STAT,d2
  810.     btst    #1,d2
  811.     bne.s    blnkit
  812.     btst    #3,d2
  813.     bne.s    blt_cop8
  814. *
  815. blt_cop4:
  816.     move.w    #$0F00,COLOR01
  817.     move.w    #$00F0,COLOR02
  818.     rts
  819. *
  820. blt_cop8:
  821.     move.w    #$0B44,COLOR01
  822.     move.w    #$04B4,COLOR02
  823.     move.w    #$08FF,COLOR03
  824.     rts
  825. *
  826. * ACE_ON asks is it already on? if so, return no error
  827. *
  828. mblit_on:
  829.     bsr.s    find_pos2
  830.     beq.s    it_worked    Already on
  831. *
  832. * Otherwise, allocate linkage area in common heap
  833. *
  834.     moveq    #varSize,d1
  835.     moveq    #0,d2        Owned by SuperBASIC
  836.     moveq    #24,d0        MT.ALCHP trap key
  837.     trap    #1
  838.     tst.l    d0        Did we get it?
  839.     bne.s    oops
  840. *
  841.     bsr    ace_cop
  842.     move.b    d2,prefix+smode(a0)
  843. *
  844.     lea.l    redraw,a2
  845.     move.l    a2,vector(a0)        Provide code address
  846.     move.l    d7,marker(a0)        Add signature
  847.     move.b    #2,prefix+limit(a0)    Update every other field
  848.     move.b    #1,prefix+count(a0)
  849.     move.b    #0,prefix+missed(a0)    Not currently used...
  850.     move.b    #0,prefix+busy(a0)
  851.     move.b    #8,prefix+chunks(a0)    Scan 8 x 2K per update
  852.     move.b    #0,prefix+soFar(a0)
  853.  
  854.     move.b    #0,prefix+flash_now(a0)
  855.     move.b    #FLASH_PERIOD,prefix+flash_tick(a0)
  856. *    move.b    #0,prefix+flash_rate(a0)
  857.  
  858. * Only turn flash on by default if running a 68040 or better?
  859.  
  860.     move.l    a0,a3        Save A0 for later
  861. *    moveq    #0,d0
  862. *    trap    #1        MT.INF
  863. *    move.b    161(a0),d0    Check CPU version
  864. *    cmp.b    #$40,d0        < 040
  865. *    bcs.s    too_old
  866.  
  867.     move.b    #FLASH_PERIOD,prefix+flash_rate(a3)
  868.  
  869. too_old:
  870.     move.l    a3,a0
  871.     moveq    #28,d0        Set up MT.LPOLL trap
  872.  
  873. trap1_out:
  874.     trap    #1
  875.  
  876. it_worked:
  877.     moveq    #0,d0
  878.     rts
  879. *
  880. find_pos2:
  881.     bsr    find_pos     Extra call for trapping
  882. oops    rts
  883. *
  884. * ACE_OFF is pretty simple too
  885. *
  886. mblit_off:
  887.     bsr.s    find_pos2    Is our interrupt linked?
  888.     bmi.s    it_worked    If not, return at once
  889. *
  890. * Remove interrupt server and deallocate linkage memory
  891. *
  892.     bsr    blt_cop
  893. *
  894. not_opened:
  895.     lea.l  -prefix(a4),a0
  896.     moveq    #29,d0        MT.RPOLL trap key
  897.     trap    #1
  898.     moveq    #25,d0        MT.RECHP trap key
  899.     bra.s    trap1_out
  900. *
  901. * ACE_FLASH 0 turns flash off. Parameters >0 set rate in frames before
  902. * change, e.g. 25 to flash on and off once every second, 5 for 5 flashes
  903. * per second, etc. Maximum 250 (change every 5 seconds, flash every 10).
  904. *
  905. flashrate:
  906.     move.w    CA.GTINT,a2    Integer fetch vector
  907.     jsr    (a2)
  908.     bne.s    no_luck
  909.  
  910.     subq.w    #1,d3
  911.     bne.s    bad_param
  912.     move.w    0(a1,a6.l),d5
  913.     cmp.w    #251,d5
  914.     bcc.s    bad_param
  915.  
  916.     bsr.s    find_pos
  917.     move.b    d5,flash_rate(a4)
  918.  
  919.     tst.b    d5
  920.     bne.s    it_worked
  921.  
  922.     clr.b    flash_now(a4)
  923.     bra.s    it_worked
  924. *
  925. bad_param:
  926.     moveq    #-15,d0    ERR.BP code
  927.  
  928. no_luck:
  929.     rts
  930. *
  931. setrate:
  932.     move.w     CA.GTINT,a2    Integer fetch vector
  933.     jsr    (a2)
  934.     bne.s    no_luck
  935.  
  936.     subq.w    #2,d3
  937.     bne.s    bad_param
  938. *
  939. * Check first parameter, number of 2K chunks to update each time
  940. *
  941.     move.w    0(a1,a6.l),d4
  942.     ble.s    bad_param
  943.  
  944.     cmp.w    #16,d4
  945.     bhi.s    bad_param
  946. *
  947. * Check second parameter, delay between updates in fields
  948. *
  949.     tst.b    2(a1,a6.l)
  950.     bne.s    bad_param    Reject if <0 or >255
  951.  
  952.     move.b    3(a1,a6.l),d3
  953.     beq.s    bad_param    Trap zero (aka 256!)
  954. *
  955.     bsr.s    find_pos
  956. *
  957.     move.b    d3,limit(a4)
  958.     move.b    d4,chunks(a4)
  959.     move.b    #1,count(a4)    Respond next field
  960.     bra.s    it_worked
  961. *
  962. * ACE_STEP% returns the current setting of CHUNKS to SuperBASIC
  963. *
  964. step:
  965.     bsr.s    find_pos
  966.     moveq    #0,d4
  967.     move.b    chunks(a4),d4
  968.     bra.s    chk_integer
  969. *
  970. * ACE_FLASH% returns the current flash rate (default 16)
  971. *
  972. flash:
  973.     bsr.s    find_pos
  974.     moveq    #0,d4
  975.     move.b    flash_rate(a4),d4
  976.     bra.s    chk_integer
  977. *
  978. * ACE_RATE% returns the current setting of LIMIT to SuperBASIC
  979. *
  980. rate:
  981.     bsr.s    find_pos
  982.     moveq    #0,d4
  983.     move.b    limit(a4),d4
  984. *
  985. * Return the integer in D4.W to SuperBASIC via the RI stack
  986. *
  987. chk_integer:
  988.     moveq    #2,d1        Number of bytes needed
  989.     move.w    BV.CHRIX,a2    Find the BV.CHRIX vector
  990.     jsr    (a2)        Allocate RI space
  991.     subq.l    #2,$58(a6)    Update BV.RIP
  992.  
  993. ret_integer:
  994.     move.l    $58(a6),a1    Get BV.RIP
  995.     move.w    d4,0(a1,a6.l)    Stack the result
  996.     moveq    #3,d4        Type = 16 bit Integer
  997.  
  998. no_error:
  999.     moveq    #0,d0        No run-time error
  1000.     rts
  1001. *
  1002. * FIND_POS points A4 at ACE variables in the interrupt list
  1003. *
  1004. * LONG link address
  1005. * LONG code address
  1006. * LONG "ACE3" marker
  1007. * BYTE count
  1008. * BYTE limit
  1009. *
  1010. * Result in A4, "ACEn" marker in D7; job ID in D1, uses D0
  1011. * Returns NOT FOUND to prior caller if the server is absent
  1012. *
  1013. find_pos:
  1014.     moveq    #0,d0        MT.INF
  1015.     trap    #1
  1016.     move.l    #'ACE3',d7
  1017.     lea.l    60(a0),a4    Locate polled list
  1018.  
  1019. find_loop:
  1020.     move.l    (a4),d0
  1021.     beq.s    not_found    Report to prior caller
  1022. *
  1023.     movea.l d0,a4
  1024.     cmp.l    marker(a4),d7    Check signature
  1025.     bne.s    find_loop
  1026. *
  1027. found_it:
  1028.     lea.l    prefix(a4),a4    Point at the data
  1029.     rts
  1030. *
  1031. not_found:
  1032.     addq.l    #4,a7        Discard return address
  1033.     moveq    #-7,d0        ERR.NF report code
  1034.     rts
  1035. *
  1036. * Mode 8 byte conversion table, generated by ACE3_BAS
  1037. *
  1038. * Index:  0..255    A B C D E F G H
  1039. * Result: 0..255    B D F H A C E G
  1040. *
  1041. byteTable:
  1042.     dc.b    0,16,1,17,32,48,33,49
  1043.     dc.b    2,18,3,19,34,50,35,51
  1044.     dc.b    64,80,65,81,96,112,97,113
  1045.     dc.b    66,82,67,83,98,114,99,115
  1046.     dc.b    4,20,5,21,36,52,37,53
  1047.     dc.b    6,22,7,23,38,54,39,55
  1048.     dc.b    68,84,69,85,100,116,101,117
  1049.     dc.b    70,86,71,87,102,118,103,119
  1050.     dc.b    128,144,129,145,160,176,161,177
  1051.     dc.b    130,146,131,147,162,178,163,179
  1052.     dc.b    192,208,193,209,224,240,225,241
  1053.     dc.b    194,210,195,211,226,242,227,243
  1054.     dc.b    132,148,133,149,164,180,165,181
  1055.     dc.b    134,150,135,151,166,182,167,183
  1056.     dc.b    196,212,197,213,228,244,229,245
  1057.     dc.b    198,214,199,215,230,246,231,247
  1058.     dc.b    8,24,9,25,40,56,41,57
  1059.     dc.b    10,26,11,27,42,58,43,59
  1060.     dc.b    72,88,73,89,104,120,105,121
  1061.     dc.b    74,90,75,91,106,122,107,123
  1062.     dc.b    12,28,13,29,44,60,45,61
  1063.     dc.b    14,30,15,31,46,62,47,63
  1064.     dc.b    76,92,77,93,108,124,109,125
  1065.     dc.b    78,94,79,95,110,126,111,127
  1066.     dc.b    136,152,137,153,168,184,169,185
  1067.     dc.b    138,154,139,155,170,186,171,187
  1068.     dc.b    200,216,201,217,232,248,233,249
  1069.     dc.b    202,218,203,219,234,250,235,251
  1070.     dc.b    140,156,141,157,172,188,173,189
  1071.     dc.b    142,158,143,159,174,190,175,191
  1072.     dc.b    204,220,205,221,236,252,237,253
  1073.     dc.b    206,222,207,223,238,254,239,255
  1074. *
  1075. * SuperBASIC extension details for the BP.INIT vector
  1076. *
  1077. define    dc.w    4+1        Four procedures
  1078.     dc.w    mblit_off-*
  1079.     dc.b    7,'ACE_OFF'
  1080.     dc.w    mblit_on-*
  1081.     dc.b    6,'ACE_ON'
  1082.     dc.w    setrate-*
  1083.     dc.b    12,'ACE_PRIORITY' Long name hence +1
  1084.     dc.w    flashrate-*
  1085.     dc.b    9,'ACE_FLASH'
  1086.     dc.w    0
  1087. *
  1088.     dc.w    3+1        Two verbose functions
  1089.     dc.w    rate-*
  1090.     dc.b    9,'ACE_RATE%'
  1091.     dc.w    flash-*
  1092.     dc.b    10,'ACE_FLASH%'
  1093.     dc.w    step-*
  1094.     dc.b    9,'ACE_STEP%'
  1095.     dc.w    0
  1096. *
  1097.     end
  1098.